home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
comm
/
mail
/
Mutt089src.lha
/
Mutt-0.89i-AMIGA
/
src
/
pager.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-28
|
49KB
|
2,148 lines
/*
* Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "mutt.h"
#include "mutt_curses.h"
#include "mutt_regex.h"
#include "keymap.h"
#include "mutt_menu.h"
#include "sort.h"
#ifdef _PGPPATH
#include "pgp.h"
#endif
#include <sys/stat.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define M_NOSHOW 0
#define M_SHOWFLAT (1 << 0)
#define M_SHOWCOLOR (1 << 1)
#define M_HIDE (1 << 2)
#define M_SEARCH (1 << 3)
#define M_TYPES (1 << 4)
#define M_SHOW (M_SHOWCOLOR | M_SHOWFLAT)
#define ISHEADER(x) ((x) == MT_COLOR_HEADER || (x) == MT_COLOR_HDEFAULT)
#define CHECK_MODE if (!hdr) \
{ \
mutt_flushinp (); \
mutt_error ("Not available in this menu."); \
break; \
}
#define CHECK_READONLY if (Context->readonly) \
{ \
mutt_flushinp (); \
mutt_error ("Mailbox is read-only."); \
break; \
}
struct q_class_t
{
int length;
int color;
char *prefix;
struct q_class_t *next, *prev;
struct q_class_t *down, *up;
};
struct syntax_t
{
int color;
short first;
short last;
};
struct line_t
{
long offset;
short type;
short continuation;
short chunks;
short search_cnt;
struct syntax_t *syntax;
struct syntax_t *search;
struct q_class_t *quote;
};
#define ANSI_OFF (1<<0)
#define ANSI_BLINK (1<<1)
#define ANSI_BOLD (1<<2)
#define ANSI_UNDERLINE (1<<3)
#define ANSI_REVERSE (1<<4)
#define ANSI_COLOR (1<<5)
typedef struct _ansi_attr {
int attr;
int fg;
int bg;
int pair;
} ansi_attr;
static short InHelp = 0;
#define NumSigLines 4
static int check_sig (const char *s, struct line_t *info, int n)
{
int count = 0;
while (n > 0 && count <= NumSigLines)
{
if (info[n].type != MT_COLOR_SIGNATURE)
break;
count++;
n--;
}
if (count == 0)
return (-1);
if (count > NumSigLines)
{
/* check for a blank line */
while (*s)
{
if (!ISSPACE (*s))
return 0;
s++;
}
return (-1);
}
return (0);
}
static void
resolve_color (struct line_t *lineInfo, int n, int cnt, int flags, int special,
ansi_attr *a)
{
int def_color; /* color without syntax hilight */
int color; /* final color */
static int last_color; /* last color set */
int search = 0, i, m;
if (!cnt)
last_color = -1; /* force attrset() */
if (lineInfo[n].continuation)
{
if (!cnt && option (OPTMARKERS))
{
SETCOLOR (MT_COLOR_MARKERS);
addch ('+');
last_color = ColorDefs[MT_COLOR_MARKERS];
}
m = (lineInfo[n].syntax)[0].first;
cnt += (lineInfo[n].syntax)[0].last;
}
else
m = n;
if (!(flags & M_SHOWCOLOR))
def_color = ColorDefs[MT_COLOR_NORMAL];
else if (lineInfo[m].type == MT_COLOR_HEADER)
def_color = (lineInfo[m].syntax)[0].color;
else
def_color = ColorDefs[lineInfo[m].type];
if ((flags & M_SHOWCOLOR) && lineInfo[m].type == MT_COLOR_QUOTED)
{
struct q_class_t *class = lineInfo[m].quote;
if (class)
{
def_color = class->color;
while (class && class->length > cnt)
{
def_color = class->color;
class = class->up;
}
}
}
color = def_color;
if (flags & M_SHOWCOLOR)
{
for (i = 0; i < lineInfo[m].chunks; i++)
{
/* we assume the chunks are sorted */
if (cnt > (lineInfo[m].syntax)[i].last)
continue;
if (cnt < (lineInfo[m].syntax)[i].first)
break;
if (cnt != (lineInfo[m].syntax)[i].last)
{
color = (lineInfo[m].syntax)[i].color;
break;
}
/* don't break here, as cnt might be
* in the next chunk as well */
}
}
if (flags & M_SEARCH)
{
for (i = 0; i < lineInfo[m].search_cnt; i++)
{
if (cnt > (lineInfo[m].search)[i].last)
continue;
if (cnt < (lineInfo[m].search)[i].first)
break;
if (cnt != (lineInfo[m].search)[i].last)
{
color = ColorDefs[MT_COLOR_SEARCH];
search = 1;
break;
}
}
}
/* handle "special" bold & underlined characters */
if (special || a->attr)
{
if (special == A_BOLD || (a->attr & ANSI_BOLD))
{
if (ColorDefs[MT_COLOR_BOLD] && !search)
color = ColorDefs[MT_COLOR_BOLD];
else
color ^= A_BOLD;
}
else if (special == A_UNDERLINE || (a->attr & ANSI_UNDERLINE))
{
if (ColorDefs[MT_COLOR_UNDERLINE] && !search)
color = ColorDefs[MT_COLOR_UNDERLINE];
else
color ^= A_UNDERLINE;
}
else if (a->attr & ANSI_REVERSE)
{
color ^= A_REVERSE;
}
else if (a->attr & ANSI_BLINK)
{
color ^= A_BLINK;
}
#ifdef HAVE_COLOR
else if (a->attr & ANSI_COLOR)
{
if (a->pair == -1)
a->pair = mutt_alloc_color (a->fg,a->bg);
color = a->pair;
}
#endif
else if (a->attr & ANSI_OFF)
{
a->attr = 0;
}
}
if (color != last_color)
{
attrset (color);
last_color = color;
}
}
static void
append_line (struct line_t *lineInfo, int n, int cnt)
{
int m;
lineInfo[n+1].type = lineInfo[n].type;
(lineInfo[n+1].syntax)[0].color = (lineInfo[n].syntax)[0].color;
lineInfo[n+1].continuation = 1;
/* find the real start of the line */
m = n;
while (m >= 0)
{
if (lineInfo[m].continuation == 0) break;
m--;
}
(lineInfo[n+1].syntax)[0].first = m;
(lineInfo[n+1].syntax)[0].last = (lineInfo[n].continuation) ?
cnt + (lineInfo[n].syntax)[0].last : cnt;
}
static void
cleanup_quote (struct q_class_t **QuoteList)
{
struct q_class_t *ptr;
while (*QuoteList)
{
if ((*QuoteList)->down)
cleanup_quote (&((*QuoteList)->down));
ptr = (*QuoteList)->next;
safe_free ((void **) &(*QuoteList)->prefix);
safe_free ((void **) QuoteList);
*QuoteList = ptr;
}
return;
}
static struct q_class_t *
classify_quote (struct q_class_t **QuoteList, const char *qptr,
int length, int *force_redraw, int *q_level)
{
struct q_class_t *q_list = *QuoteList;
struct q_class_t *class = NULL, *tmp = NULL, *ptr;
char *tail_qptr;
int offset, tail_lng;
/* Did I mention how much I like emulating Lisp in C? */
/* classify quoting prefix */
while (q_list)
{
if (length <= q_list->length)
{
if (strncmp (qptr, q_list->prefix, length) == 0)
{
/* same prefix: return the current class */
if (length == q_list->length)
return q_list;
/* found shorter common prefix */
if (tmp == NULL)
{
/* add a node above q_list */
tmp = (struct q_class_t *) safe_calloc (1, sizeof (struct q_class_t));
tmp->prefix = (char *) safe_calloc (1, length + 1);
strncpy (tmp->prefix, qptr, length);
tmp->length = length;
if (*q_level >= ColorQuoteUsed)
*q_level = 1;
else
(*q_level)++;
tmp->color = ColorQuote[(*q_level) - 1];
/* replace q_list by tmp in the top level list */
if (q_list->next)
{
tmp->next = q_list->next;
q_list->next->prev = tmp;
}
if (q_list->prev)
{
tmp->prev = q_list->prev;
q_list->prev->next = tmp;
}
/* make q_list a child of tmp */
tmp->down = q_list;
q_list->up = tmp;
/* q_list has no siblings */
q_list->next = NULL;
q_list->prev = NULL;
/* update the root if necessary */
if (q_list == *QuoteList)
*QuoteList = tmp;
/* tmp should be the return class too */
class = tmp;
/* next class to test */
q_list = tmp->next;
}
else
{
/* save the next sibling for later */
ptr = q_list->next;
/* unlink q_list from the top level list */
if (q_list->next)